;
('use strict')
var accounts = require('../config').accounts
var request = require('superagent')
var sendEmail = require('./sendEmail')
var cheerio = require('cheerio')
var dateFormat = require('dateformat')
var fs = require('fs')
var crypto = require('crypto')
var valicationAC = require('../config').valicationAC
var cluster = require('cluster')

var logger = require('./log4js').getLogger()
var debuglogger = require('./log4js').getLogger('debug')

var headers = {
  Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  'Accept-Encoding': 'gzip, deflate, br',
  'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
  Connection: 'keep-alive',
  'Content-Type': 'application/x-www-form-urlencoded',
  Cookie: 'locale=zh-CN;',
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}

var passporturl = 'https://passport.bitmain.com',
  shopurl = 'https://shop.bitmain.com',
  urls = {
    login: passporturl + '/login',
    success: passporturl + '/success',
    orderdetal: shopurl + '/user/orderDetails.htm',
    addProd: shopurl + '/user/orderDetails.htm?m=add&count=1&fitting=&pid=',
    prodList: shopurl + '/main.htm?lang=zh',
    editmount: shopurl + '/user/orderDetails.htm?m=count',
    genOrder: shopurl + '/user/orderDetails.htm?m=y',
    orderConfirmBase: shopurl + '/user/orderConfirm.htm',
    orderConfirm: shopurl + '/user/orderConfirm.htm?m=y',
    validateImg: shopurl + '/user/orderConfirm.htm?m=validateImag'
  }

var damaURL = 'http://v1-http-api.jsdama.com/api.php?mod=php&act=upload'
var reportErrURL = 'http://v1-http-api.jsdama.com/api.php?mod=php&act=error'
var pointURL = 'http://v1-http-api.jsdama.com/api.php?mod=php&act=point'

let LoginCookie = [],
  ShopCookie = []

let pid = '',
  cartid = '',
  hidden_country = '',
  hidden_stateCode = '',
  deliveryOption = '',
  operatorId = '',
  addrId = '',
  payCurrency = '',
  shipMethod = '',
  shipMethodValue = '',
  validate = '',
  shopCarts = '',
  imagi = 0,
  date1 = 0
let goods = {}
let account = {}

var AutoBuy = {
  constructor: function (who) {
    let that = this
    debuglogger.debug(`${JSON.stringify(that)}`)
    debuglogger.debug(`${JSON.stringify(this)}`)
    account = who
    goods = account.goods

    debuglogger.debug(
      `[${account.procid}] >> account: ${JSON.stringify(account)}`
    )

    that.cookie = {
      value: null,
      expires: null
    }

    that.init()
  },

  init: function () {
    let that = this

    logger.info(`[${account.procid}] ============ 抢购开始 ============`)
    logger.info(`[${account.procid}] 查询验证码点数是否足够`)
    debuglogger.debug(`[${account.procid}] >> ` + 'query point')

    var postLoad = {
      user_name: valicationAC.username,
      user_pw: valicationAC.password
    }
    request
      .post(pointURL)
      .send(postLoad)
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + res.text)
        var points = JSON.parse(res.text).data
        if (points < 100) {
          logger.info(
            `[${account.procid}] >> 点数不足100，请及时充值，剩余点数: ` +
            points
          )
        } else {
          logger.info(`[${account.procid}] >> 点数充足，剩余点数: ` + points)
        }
        that.Buy()
      })
  },

  sendNotice: function () {
    let that = this
    logger.info(`[${account.procid}] >> 抢购完毕`)
    sendEmail(
      '蚂蚁矿机抢购完毕',
      account.user + '，抢购完毕。 ' + new Date(),
      account.mail,
      that.finish
    )
  },

  finish: function () {
    logger.info(`[${account.procid}] >> 通知邮件已发送到: ` + account.mail)
    logger.info(
      `[${account.procid}] >> ====== ${account.user}的订单抢购完毕 ======`
    )
    var date2 = new Date(); //结束时间
    var date3 = (date2.getTime() - date1.getTime()) / 1000 //时间差的毫秒数
    logger.info(
      `[${account.procid}] >> ====== 抢购耗时 ${date3} 秒 ======`
    )
    process.exit(0)
  },

  /** 代码逻辑如下：
   * 1. 访问 orderDetails.htm
   * 2. 跳转到 passport.bitmain.com/login
   * 3. 登录 login
   * 4. 跳转到 orderDetails.htm
   * 5. 添加矿机到购物车
   * 6. 生成订单
   * 7. 支付
   */

  // 抢购
  Buy: function () {
    let that = this
    // logger.info(`[${account.procid}] >> .... `)
    that.Login()
    // that._getShipment()

    // var validateImg = 'validateImage.jsp?t=' + Math.random()
    // logger.info('validImg is: ' + validateImg)
  },

  Login: function () {
    let that = this

    //获取shop的cookie

    debuglogger.debug(`[${account.procid}] >> get shop cookie`)

    var loginLocation = ''
    request
      .get(shopurl)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .end(function (err, res) {
        ShopCookie = res.headers['set-cookie']
        debuglogger.debug(`[${account.procid}] >> ShopCookie: ` + ShopCookie)
        request
          .get(urls.orderdetal)
          .set(headers)
          .set({
            Cookie: ShopCookie
          })
          .end(function (err, res) {
            debuglogger.debug(`[${account.procid}] >> URL: ` + res.request.url)
            LoginCookie = res.headers['set-cookie']
            debuglogger.debug(
              `[${account.procid}] >> LoginCookie: ` + LoginCookie
            )
            var $ = cheerio.load(res.text)
            let _xsrf = $('[name="_xsrf"]').val()
            debuglogger.debug(`[${account.procid}] >> _xsrf: ` + _xsrf)
            let lt = $('[name="lt"]').val()
            debuglogger.debug(`[${account.procid}] >> lt: ` + lt)
            let service = $('[name="service"]').val()
            debuglogger.debug(`[${account.procid}] >> service: ` + service)
            var loginPara = {
              _xsrf: _xsrf,
              lt: lt,
              service: service
            }
            if ($('[name="captchaId"]').length > 0) {
              //如果登录遇到验证码，先获取登录验证码再登录
              loginPara.captchaId = $('[name="captchaId"]').val()
              let loginimgurl = $('#image').attr('src')
              debuglogger.debug(
                `[${account.procid}] >> loginimgurl: ` +
                passporturl +
                loginimgurl
              )
              that._getLoginVImg(passporturl + loginimgurl, loginPara)
            } else {
              // 回调登录
              that._Login(loginPara, '')
            }
          })
      })
  },

  _getLoginVImg: function (detailUrl, loginPara) {
    let that = this
    logger.info(`[${account.procid}] >> 猜测登陆验证码`)
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start get Image: ' + detailUrl
    )

    var time = new Date().getTime()

    var imgName = 'imgs/' + account.name + time + '.jpg'
    var stream = fs.createWriteStream(imgName)
    var req = request
      .get(detailUrl)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
    req.pipe(stream)
    stream.on('finish', function () {
      that._renameLogin(imgName, loginPara)
    })
  },

  _renameLogin: function (filename, loginPara) {
    let that = this
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start rename Image: ' + filename
    )

    var _dig = ''
    var start = new Date().getTime()
    var md5sum = crypto.createHash('md5')
    var stream = fs.createReadStream(filename)
    stream.on('data', function (chunk) {
      md5sum.update(chunk)
    })
    stream.on('end', function () {
      let str = md5sum.digest('hex').toUpperCase()
      debuglogger.debug(
        `[${account.procid}] >> ` +
        '文件:' +
        filename +
        ',MD5签名为:' +
        str +
        '.耗时:' +
        (new Date().getTime() - start) / 1000.0 +
        '秒'
      )
      var newname = account.user + str + '.jpg'
      fs.rename(filename, 'imgs/' + newname, function (err) {
        if (err) {
          debuglogger.debug(`[${account.procid}] >> ` + '重命名失败！')
          try {
            that.sendNotice()
          } catch (e) {
            debuglogger.debug('\r\n', e, '\r\n', e.stack)
          }
        } else {
          debuglogger.debug(`[${account.procid}] >> ` + '重命名成功！')
          that._getLoginAnswer('imgs/' + newname, loginPara)
        }
      })
    })
  },

  _getLoginAnswer: function (filename, loginPara) {
    let that = this
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start get answer: ' + filename
    )

    var postLoad = {
      user_name: valicationAC.username,
      user_pw: valicationAC.password,
      yzm_minlen: 6,
      yzm_maxlen: 6,
      yzmtype_mark: valicationAC.logintype,
      zztool_token: ''
    }
    request
      .post(damaURL)
      .attach('upload', filename)
      .accept('application/json')
      .field(postLoad)
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + res.text)
        var answer = JSON.parse(res.text).data.val
        debuglogger.debug(`[${account.procid}] >> ` + answer)
        // that._getValidate(answer)
        that._Login(loginPara, answer)
      })
  },

  _Login: function (loginPara, captcha) {
    let that = this
    // 登录
    logger.info(`[${account.procid}] >> ` + '开始登陆')
    var detailUrl = ''
    debuglogger.debug(`${JSON.stringify(account)}`)
    var sendc = {
      username: account.user,
      password: account.password,
      lt: loginPara.lt,
      service: loginPara.service,
      _xsrf: loginPara._xsrf
    }
    if (captcha != '') {
      sendc.captcha = captcha
      sendc.captchaId = loginPara.captchaId
    }

    debuglogger.debug(`[${account.procid}] >> ` + JSON.stringify(sendc))
    request
      .post(urls.login)
      .set(headers)
      .set('Cookie', LoginCookie)
      .type('form')
      .send(sendc)
      .redirects(0) // 防止页面重定向
      .end(function (err, res) {
        debuglogger.debug(
          `[${account.procid}] >> ` + ' URL: ' + res.request.url
        )
        detailUrl = res.headers.location
        debuglogger.debug(`[${account.procid}] >> ` + 'Real URL: ' + detailUrl)
        debuglogger.debug(
          `[${account.procid}] >> ` + 'login status: ' + res.status
        )
        LoginCookie.concat(res.headers['set-cookie'])
        debuglogger.debug(
          `[${account.procid}] >> ` + 'login cookie: ' + LoginCookie
        )
        if (detailUrl) {
          logger.info(`[${account.procid}] >> 登陆成功`)
          that._viweCart(detailUrl)
        } else {
          logger.info(`[${account.procid}] >> 登陆失败`)
          process.exit(0)
        }
      })
  },

  _viweCart: function (location) {
    let that = this
    debuglogger.debug(`[${account.procid}] >> ` + 'view cart: ' + location)

    request
      .get(location)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .end(function (err, res) {
        // logger.info(err)
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        // var $ = cheerio.load(res.text)
        // logger.info($('body').text())
        that._getProdInfo()
      })
  },

  _getProdInfo: function () {
    let that = this

    request
      .get(urls.prodList)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        var $ = cheerio.load(res.text)
        $('div.homepage-prtList')
          .find('ul')
          .find('li')
          .map(function () {
            if (
              $(this)
              .text()
              .indexOf(goods.name) > 0 &&
              $(this)
              .text()
              .indexOf(goods.except) < 0
            ) {
              var pidURL = $(this).find('a')[0].attribs['href']
              debuglogger.debug(`[${account.procid}] >> ` + pidURL)
              pid = pidURL.substr(pidURL.indexOf('pid=') + 4)
              that._addToCart()
            } //如果没有找到匹配的产品
          })
      })
  },

  _addToCart: function () {
    let that = this

    request
      .get(urls.addProd + pid)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        var $ = cheerio.load(res.text)
        logger.info(
          `[${account.procid}] >> ` +
          $('.info-box')
          .text()
          .trim()
          .replace(/\s+/g, '')
        )
        cartid = $('#shopCarts').val()
        debuglogger.debug(`[${account.procid}] >> ` + cartid)
        that._getCartID()
      })
  },

  _getCartID: function () {
    let that = this

    request
      .get(urls.orderdetal)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        // logger.info(res)
        var $ = cheerio.load(res.text)
        // logger.info($('body').text())
        cartid = $('span.check-one').attr('cart-id')
        debuglogger.debug(`[${account.procid}] >> cartid: ` + cartid)
        var _goods = $('.goods')
          .text()
          .trim()
        debuglogger.debug(`[${account.procid}] >> ` + _goods)
        that._updateMount(cartid)
      })
  },

  _updateMount: function (cartid) {
    let that = this

    request
      .post(urls.editmount)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .send({
        id: cartid,
        count: goods.mount,
        ty: 'set'
      })
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        // logger.info(res.text)
        var result = JSON.parse(res.text).Message
        if (result == 'ok') {
          logger.info(
            `[${account.procid}] >> ` +
            '更新订单数量成功! 数量为: ' +
            goods.mount
          )
          that._genOrder()
        } else {
          logger.info(
            `[${account.procid}] >> ` + '更新订单数量失败!  : ' + result
          )
          try {
            that.sendNotice()
          } catch (e) {
            debuglogger.debug('\r\n', e, '\r\n', e.stack)
          }
        }
      })
  },

  _genOrder: function () {
    let that = this

    logger.info(`[${account.procid}] >> 准备生成订单`)
    request
      .post(urls.genOrder)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
      .type('form')
      .send({
        shopCarts: cartid
      })
      .end(function (err, res) {
        // logger.info(err)
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        var $ = cheerio.load(res.text)
        // logger.info($('.sub-title').text())
        var inputs = $('#orderConfirmForm').find('input')
        inputs.each(function () {
          debuglogger.debug(
            `[${account.procid}] >> ` +
            $(this).attr('id') +
            ': ' +
            $(this).val()
          )
          if ($(this).attr('id') == 'hidden_country')
            hidden_country = $(this).val()

          if ($(this).attr('id') == 'hidden_stateCode')
            hidden_stateCode = $(this).val()

          if ($(this).attr('id') == 'deliveryOption')
            deliveryOption = $(this).val()

          if ($(this).attr('id') == 'operatorId') operatorId = $(this).val()

          if ($(this).attr('id') == 'addrId') addrId = $(this).val()

          if ($(this).attr('id') == 'payCurrency') payCurrency = $(this).val()

          if ($(this).attr('id') == 'shipMethod') shipMethod = $(this).val()

          if ($(this).attr('id') == 'shipMethodValue')
            shipMethodValue = $(this).val()

          if ($(this).attr('id') == 'validate') validate = $(this).val()

          if ($(this).attr('id') == 'shopCarts') shopCarts = $(this).val()
        })
        var addresses = $('.addrTable').find('tr')
        addresses.each(function () {
          debuglogger.debug(
            `[${account.procid}] >> ` +
            $(this).attr('addrid') +
            ': ' +
            $(this).attr('addruuid')
          )
          if ($(this).attr('class') == 'current default')
            addrId = $(this).attr('addruuid')
        })
        var expresses = $('#express').find('a')
        expresses.each(function () {
          debuglogger.debug(
            `[${account.procid}] >> ` +
            $(this).attr('billnamecode') +
            ': ' +
            $(this).attr('billnamevalue') +
            '  ' +
            $(this)
            .text()
            .trim()
          )
          if (
            $(this)
            .text()
            .trim() == '顺丰(SF)'
          ) {
            shipMethod = $(this).attr('billnamecode')
            shipMethodValue = $(this).attr('billnamevalue')
          }
        })
        // that._getValidate()
        that._getVImg(urls.validateImg)
      })
  },

  _getVImg: function (detailUrl) {
    let that = this
    logger.info(`[${account.procid}] >> 猜测订单验证码`)
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start get Image: ' + detailUrl
    )

    var time = new Date().getTime()

    var imgName = 'imgs/' + account.name + time + '.jpg'
    var stream = fs.createWriteStream(imgName)
    var req = request
      .get(detailUrl)
      .set(headers)
      .set({
        Cookie: ShopCookie
      })
    req.pipe(stream)
    stream.on('finish', function () {
      that._rename(imgName)
    })
  },

  _rename: function (filename) {
    let that = this
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start rename Image: ' + filename
    )

    var _dig = ''
    var start = new Date().getTime()
    var md5sum = crypto.createHash('md5')
    var stream = fs.createReadStream(filename)
    stream.on('data', function (chunk) {
      md5sum.update(chunk)
    })
    stream.on('end', function () {
      let str = md5sum.digest('hex').toUpperCase()
      debuglogger.debug(
        `[${account.procid}] >> ` +
        '文件:' +
        filename +
        ',MD5签名为:' +
        str +
        '.耗时:' +
        (new Date().getTime() - start) / 1000.0 +
        '秒'
      )
      var newname = account.name + str + '.jpg'
      fs.rename(filename, 'imgs/' + newname, function (err) {
        if (err) {
          debuglogger.debug(`[${account.procid}] >> ` + '重命名失败！')
          try {
            that.sendNotice()
          } catch (e) {
            debuglogger.debug('\r\n', e, '\r\n', e.stack)
          }
        } else {
          debuglogger.debug(`[${account.procid}] >> ` + '重命名成功！')
          that._getAnswer('imgs/' + newname)
        }
      })
    })
  },

  _getAnswer: function (filename) {
    let that = this
    debuglogger.debug(
      `[${account.procid}] >> ` + 'start get answer: ' + filename
    )

    var postLoad = {
      user_name: valicationAC.username,
      user_pw: valicationAC.password,
      yzm_minlen: valicationAC.answerminlength,
      yzm_maxlen: valicationAC.answermaxlength,
      yzmtype_mark: valicationAC.paytype,
      zztool_token: ''
    }
    request
      .post(damaURL)
      .attach('upload', filename)
      .accept('application/json')
      .field(postLoad)
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + res.text)
        if (JSON.parse(res.text).data == '') {
          debuglogger.debug(
            `[${account.procid}] >> get answer out off time, try again`
          )
          that._getAnswer(filename)
        } else {
          var answer = JSON.parse(res.text).data.val
          var id = JSON.parse(res.text).data.id
          debuglogger.debug(`[${account.procid}] >> ` + answer)
          that._getValidate(answer, id)
        }
      })
  },

  _getValidate: function (answer, id) {
    let that = this

    debuglogger.debug(`[${account.procid}] >> ` + 'get Validate Result')
    // logger.info('shopcookie: ' + ShopCookie)
    request
      .get(urls.orderConfirmBase)
      .set(headers)
      .set({
        Cookie: ShopCookie,
        'Content-Type': 'application/json'
      })
      .query({
        m: 'validate',
        calculationResult: answer
      })
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + 'URL: ' + res.request.url)
        // logger.info(res.status)
        // logger.info(res.headers['set-cookie'])
        var validateCookie = res.headers['set-cookie']
        // logger.info(ShopCookie)
        // ShopCookie[2] = validateCookie[0]
        // logger.info(ShopCookie)
        logger.info(`[${account.procid}] >> ` + res.text)
        if (JSON.parse(res.text).Message == '回答错误，请重新输入') {
          logger.info(`[${account.procid}] >> ` + '未通过验证，重新验证')
          that._reportErr(id)
          // that._getVImg(urls.validateImg)
        } else that._submitOrder()
      })
  },

  _reportErr: function (id) {
    let that = this

    debuglogger.debug(`[${account.procid}] >> ` + 'report answer err')

    var postLoad = {
      user_name: valicationAC.username,
      user_pw: valicationAC.password,
      yzm_id: id
    }
    request
      .post(reportErrURL)
      .accept('application/json')
      .send(postLoad)
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> ` + res.text)
        var result = JSON.parse(res.text).result
        debuglogger.debug(`[${account.procid}] >> ` + result)
        that._getVImg(urls.validateImg)
      })
  },

  _submitOrder: function () {
    let that = this

    logger.info(`[${account.procid}] >> 猜测订单验证码成功，生成订单`)
    var send = {
      // hidden_country: 'CN',
      // hidden_stateCode: '440000',
      deliveryOption: '0',
      operatorId: '0',
      addrId: addrId,
      payCurrency: '',
      shipMethod: shipMethod,
      shipMethodValue: shipMethodValue,
      validate: '',
      shopCarts: '',
      shopCartCoupons: '',
      orderInfo: ''
    }

    debuglogger.debug(
      `[${account.procid}] >> send form: ${JSON.stringify(send)}`
    )

    var _shopCookie = []
    // logger.info(ShopCookie)
    for (let x in ShopCookie) {
      // logger.info(ShopCookie[x])
      var _arr = ShopCookie[x].split(';')
      // logger.info(_arr[0])
      _shopCookie.push(_arr[0])
    }
    _shopCookie.push('locale=zh-CN;')
    debuglogger.debug(`[${account.procid}] >> _shopCookie ` + _shopCookie)
    request
      .post(urls.orderConfirm)
      .set(headers)
      .set({
        Cookie: _shopCookie,
        Referer: urls.orderConfirmBase,
        // Host: shopurl,
        'Upgrade-Insecure-Requests': 1
      })
      .type('form')
      .send(send)
      // .redirects(0) // 防止页面重定向
      .end(function (err, res) {
        debuglogger.debug(`[${account.procid}] >> URL: ${res.request.url}`)
        debuglogger.debug(`[${account.procid}] >> ${res.status}`)
        if (res.status == '200') {
          var $ = cheerio.load(res.text)
          logger.info(`[${account.procid}] >> ` + $('#system_msg_msg').text())
        }
        let detailUrl = res.headers.Location
        debuglogger.debug(`[${account.procid}] >> Real URL: ${detailUrl}`)
        try {
          logger.info(`[${account.procid}] >> 订单生成成功，请及时支付`)
          that.sendNotice()
        } catch (e) {
          debuglogger.debug('\r\n', e, '\r\n', e.stack)
        }
      })
  },

  // 验证登录，如果凭证没过期，无需重新验证
  _verify: function (cb) {
    logger.info('cookie expires: ' + this.cookie.expires)
    Date.now() > this.cookie.expires ?
      this._login(cb) :
      cb(this.cookie, '/success')
  }
}

if (cluster.isWorker) {
  date1 = new Date(); //开始时间
  process.send(`worker ${cluster.worker.id} started...`)
  var who = accounts[cluster.worker.id - 1]
  who.procid = cluster.worker.id - 1
  AutoBuy.constructor(who)
}